#include "b_algo_filter.h"

#include "stdint.h"
int b_algo_moving_average(int in_data, int *filter_buff, uint16_t moving_length, int *diff)
{
    if (moving_length == 0 || filter_buff == 0)
    {
        return -1;
    }
    uint8_t j;
    int     sum = in_data, max = in_data, min = in_data;  //去除最大最小
    for (j = moving_length - 1; j > 0; j--)               //滑动
    {
        filter_buff[j] = filter_buff[j - 1];
        max            = filter_buff[j] > max ? filter_buff[j] : max;
        min            = filter_buff[j] < min ? filter_buff[j] : min;
        sum += filter_buff[j];  //求和
    }
    filter_buff[0] = in_data;  //放入新的数据
    if (diff != 0)
    {
        *diff = max - min;
    }

    sum = sum - max - min;
    return (sum / (moving_length - 2));
}

int b_algo_average(int in_data, int *out_data, uint16_t *avg_count, int *avg_buff,
                   uint16_t avg_length)
{
    if (out_data == 0 || avg_buff == 0)
    {
        return -1;
    }

    avg_buff[(*avg_count)++] = in_data;
    if (*avg_count >= avg_length)
    {
        uint16_t i;
        long     sum = 0;
        for (i = 0; i < avg_length; i++)
        {
            sum += avg_buff[i];
        }
        *out_data  = sum / avg_length;
        *avg_count = 0;
        return 1;
    }
    return 0;
}

int b_algo_limter_elimination(b_algo_limter_elimination_t *self, int in_data, int limter,
                              int elimination)
{
    int diff = in_data - self->last_data;

    if (diff < 0 && self->dir == 1)  //方向不一致
    {
        self->dir = 0;
        return self->last_data;
    }
    else if (diff > 0 && self->dir == 0)
    {
        self->dir = 1;
        return self->last_data;
    }

    if (abs(diff) > limter)
    {
        self->limter_cnt++;
        if (self->limter_cnt > 3)  //最大限幅次数
        {
            self->last_data = in_data;
        }
        return self->last_data;
    }

    if (abs(diff) < elimination)
    {
        self->elimination_cnt = 0;
        if (self->elimination_cnt > 10)
        {
            self->last_data = in_data;
        }
        return self->last_data;
    }
    self->elimination_cnt = 0;
    self->limter_cnt      = 0;
    return in_data;
}
